package com.heima.media.service.Impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.enums.MediaEnum;
import com.heima.common.util.UserThreadLocalUtil;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.dto.WmNewsDto;
import com.heima.media.dto.WmNewsPageDto;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmNewsMaterial;
import com.heima.media.mapper.WmNewsMapper;
import com.heima.media.service.IAuditService;
import com.heima.media.service.IWmNewsMaterialService;
import com.heima.media.service.IWmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-07-29
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements IWmNewsService {

    @Autowired
    private IWmNewsMaterialService newsMaterialService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Value("${topic.upDownTopic}")
    private String upDownTopic;

    /**
     * 查询当前自媒体用户发布自媒体文章列表
     *
     * @param wmNewsPageDto 查询条件
     * @return
     */
    @Override
    public ResponseResult listByCondition(WmNewsPageDto wmNewsPageDto) {
        //1.构建分页查询对象
        Page<WmNews> wmNewsPage = new Page<>(wmNewsPageDto.getPage(), wmNewsPageDto.getSize());
        //2.构建查询条件对象
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        //2.1 设置查询channelld 图文频道ID
        if (ObjectUtils.isNotEmpty(wmNewsPageDto.getChannelId())) {
            queryWrapper.eq(WmNews::getChannelId, wmNewsPageDto.getChannelId());
        }
        //2.2 设置文章状态
        if (ObjectUtils.isNotEmpty(wmNewsPageDto.getStatus())) {
            queryWrapper.eq(WmNews::getStatus, wmNewsPageDto.getStatus());
        }
        //2.3 设置模糊查询
        if (StringUtils.isNotEmpty(wmNewsPageDto.getKeyword())) {
            queryWrapper.like(WmNews::getTitle, wmNewsPageDto.getKeyword());
        }
        //2.4 设置开始结束日期
        if (ObjectUtils.isNotEmpty(wmNewsPageDto.getBeginPubDate()) && ObjectUtils.isNotEmpty(wmNewsPageDto.getEndPubDate())) {
            queryWrapper.between(WmNews::getPublishTime, wmNewsPageDto.getBeginPubDate(), wmNewsPageDto.getEndPubDate());
        }
        //2.5 设置自媒体用户id 要查询当前登录用户
        User user = UserThreadLocalUtil.get();
        Integer userId = user.getUserId();
        queryWrapper.eq(WmNews::getUserId, userId);
        //2.6 设置倒叙查询
        queryWrapper.orderByDesc(WmNews::getPublishTime);
        //3.执行查询
        this.page(wmNewsPage, queryWrapper);

        //4.封装返回结果
        return new PageResponseResult(wmNewsPageDto.getPage(), wmNewsPageDto.getSize(), wmNewsPage.getTotal(), wmNewsPage.getRecords());
    }

    @Autowired
    private IAuditService auditService;

    /**
     * 自媒体文章发布：保存自媒体文章；保存文章跟素材关系
     *
     * @param wmNewsDto
     * @return
     */
    @Override
    @GlobalTransactional
    public ResponseResult submit(WmNewsDto wmNewsDto) {

        //1.获取登录用户自媒体
        User user = UserThreadLocalUtil.get();
        if (user == null && user.getUserId() == null) {
            return ResponseResult.errorResult(401, "请登录后操作");
        }
        //2.创建媒体文章对象，属性赋值
        WmNews wmNews = new WmNews();
        //2.1 将前端提交的dto相同属性copy到文章对象
        BeanUtils.copyProperties(wmNewsDto, wmNews);
        //2.2 手动给其他属性赋值
        wmNews.setUserId(user.getUserId());
        wmNews.setSubmitedTime(new Date());
        if (ObjectUtils.isEmpty(wmNewsDto.getPublishTime())) {
            wmNews.setPublishTime(new Date());
        }
        //2.3 设置封面属性
        setWmnewImage(wmNews, wmNewsDto);

        //3. 执行保存
        this.save(wmNews);

        //4. 保存自媒体文章跟素材引用关系
        //4.1 获取文章正文中素材
        List<ImageDto> contentImages = getIamgeFromContent(wmNews.getContent());
        //4.2 获取文章封面中素材
        List<ImageDto> coverImages = wmNewsDto.getImages();
        //4.3 执行保存
        saveArticleMaterialRelation(contentImages, MediaEnum.MATERIAL_TYPE_REF_TYPE_CONTENTIMG.getVal(), wmNews.getId());
        saveArticleMaterialRelation(coverImages, MediaEnum.MATERIAL_TYPE_REF_TYPE_CONVERIMG.getVal(), wmNews.getId());

        //TODO 4.异步对自媒体文章进行审核-由线程池中线程来进行执行
        auditService.audit(wmNews);

        return ResponseResult.okResult();
    }

    /**
     * 将文章跟素材建立关联
     *
     * @param imageDtoList 内容图片集合 或者 正文图片集合
     * @param type         0：内容引用  1：封面引用
     * @param newsId       文章ID
     */
    @GlobalTransactional
    private void saveArticleMaterialRelation(List<ImageDto> imageDtoList, Integer type, Integer newsId) {

        int ord = 0;
        if (ObjectUtils.isNotEmpty(imageDtoList)) {
            for (ImageDto imageDto : imageDtoList) {
                //创建文章素材中间表对象 保存关系
                WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
                wmNewsMaterial.setMaterialId(imageDto.getId());
                wmNewsMaterial.setNewsId(newsId);
                wmNewsMaterial.setType(type);
                wmNewsMaterial.setOrd(ord++);
                newsMaterialService.save(wmNewsMaterial);
            }
        }

    }

    /**
     * 处理文章封面，封面类型
     *
     * @param wmNews
     * @param wmNewsDto
     */
    @GlobalTransactional
    private void setWmnewImage(WmNews wmNews, WmNewsDto wmNewsDto) {

        //1.得到前端提交的封面类型
        Integer type = wmNews.getType();
        List<ImageDto> images = wmNewsDto.getImages();
        String imageStr = "";

        switch (type) {
            case 0:
                //用户选择无图
                wmNews.setType(0);
                wmNews.setImages(null);
                break;
            case 1:
                //用户选择单图
                wmNews.setType(1);
                ImageDto imageDto = images.get(0);
                wmNews.setImages(imageDto.getUrl());
                break;
            case 3:
                //用户选择多图
                wmNews.setType(3);
                imageStr = images.stream().map(ImageDto::getUrl).collect(Collectors.joining(","));
                wmNews.setImages(imageStr);
                break;
            case -1:
                //用户选择自动,从正文中获取图片，当图片数量大于1小于3 设置为单图 、当图片大于等于3设置多图、当没有图片设置为无图
                List<ImageDto> list = getIamgeFromContent(wmNewsDto.getContent());
                int size = list.size();
                if (size > 0 && size < 3) {
                    //单图 截取第一张图片作为封面
                    wmNews.setType(1);
                    ImageDto imageDto1 = list.get(0);
                    wmNews.setImages(imageDto1.getUrl());
                } else if (size >= 3) {
                    //多图 截取前三张图片
                    List<ImageDto> imageDtoList = list.subList(0, 3);
                    imageStr = imageDtoList.stream().map(ImageDto::getUrl).collect(Collectors.joining(","));
                    wmNews.setType(3);
                    wmNews.setImages(imageStr);
                } else {
                    //无图
                    wmNews.setType(0);
                    wmNews.setImages(null);
                }

                break;
        }


    }

    /**
     * 从文章正文中获取图片
     *
     * @param content [{type:"text",value:"文本"},{type:"image",value:"http://l92.168.137.136:9000/1.png"}]
     * @return
     */
    private List<ImageDto> getIamgeFromContent(String content) {

        //1.将内容转为JSON数组--List<contentDto>
        List<ContentDto> contentDtos = JSON.parseArray(content, ContentDto.class);
        //2.遍历获取图片数据
        List<ImageDto> imageDtos = new ArrayList<>();
        for (ContentDto contentDto : contentDtos) {
            if ("image".equals(contentDto.getType())) {
                ImageDto imageDto = new ImageDto();
                imageDto.setId(contentDto.getId());
                imageDto.setUrl(contentDto.getValue());
                imageDtos.add(imageDto);
            }
        }
        return imageDtos;
    }

    /**
     * 修改文章上下架状态
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        //1.根据文章id 获取文章对象
        WmNews wmNews = this.getById(dto.getId());
        //1.1 判断文章是否存在
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //2.修改文章上下架状态
        Integer enable = dto.getEnable();
        wmNews.setEnable(enable == 0 ? false : true);
        this.updateById(wmNews);

        //3.发送 kafka消息 实现文章表的上下架
        HashMap<String, Object> map = new HashMap<>();
        map.put("articleId", wmNews.getArticleId());
        map.put("isDown", !wmNews.getEnable());
        kafkaTemplate.send(upDownTopic, JSON.toJSONString(map));
        return ResponseResult.okResult();
    }
}
